using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using ClientTools.Library.DataTypes.Umbraco;
using ClientTools.Library.Interfaces;

namespace ClientTools.Client.Controls.Media
{
    public partial class UcMedia : BaseUserControl, IUserControl
    {

        private IMedia actMedia;

        public UcMedia()
        {
            InitializeComponent();
        }

        #region I_UserControl Member

        public void SetData(Library.Settings.Profile profile)
        {
            ActProfile = profile;
            ActProfile.InitProvider();
            ActProvider = ActProfile.ProviderObject;

            if (!ImplementsMedia())
            {
                Enabled = false;
                return;
            }

            actMedia = (IMedia)ActProvider;
            ClearData();
            Enabled = true;
        }

        public string Header
        {
            get { return "Media Upload"; }
        }

        public Image ButtonImage
        {
            get { return tsbAddImage.Image; }
        }

        public int Sort
        {
            get { return 3; }
        }

        public bool ShowDelimiter
        {
            get { return true; }
        }

        public string ButtonText
        {
            get { return "Media Upload"; }
        }

        #endregion

        private void ClearData()
        { 
            tvMedias.Nodes.Clear();
            SplitContainer1.Enabled = false;
        }

        private void TsbMediasClick(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            TvMediasNodeMouseClick(null, null);

            tvMedias.SuspendLayout();
            tvMedias.Nodes.Clear();

            var medias = actMedia.GetRootMedias(true);
            AddChildNodes(medias, tvMedias.Nodes);

            tvMedias.ExpandAll();
            tvMedias.ResumeLayout();

            SplitContainer1.Enabled = true;

            Cursor = Cursors.Default;
        }

        private void TvMediasNodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            tsbAddFile.Enabled = false;
            tsbAddFolder.Enabled = false;
            tsbAddImage.Enabled = false;
            tsbAddStructure.Enabled = false;
            tsbDeleteMedia.Enabled = false;
            
            if (e == null || e.Node == null) 
                return;
            
            tsbDeleteMedia.Enabled = true;
            switch (((Node)e.Node.Tag).NodeTypeAlias)
            {
                case "Folder":
                    tsbAddFile.Enabled = true;
                    tsbAddFolder.Enabled = true;
                    tsbAddImage.Enabled = true;
                    tsbAddStructure.Enabled = true;
                    break;
                default:
                    break;
            }
        }

        private static void AddChildNodes(IEnumerable<Node> umbracoMedias, TreeNodeCollection treeNodes)
        {
            foreach (var umbracoMedia in umbracoMedias)
            {
                var treeNode = treeNodes.Add(umbracoMedia.Name);
                treeNode.Tag = umbracoMedia;
                SetImageIndex(treeNode, umbracoMedia.NodeTypeAlias);
                AddChildNodes(umbracoMedia.Children, treeNode.Nodes);
            }
        }

        private static void SetImageIndex(TreeNode node, String nodeType)
        {
            switch (nodeType)
            {
                case "Folder":
                    node.ImageIndex = 0;
                    node.SelectedImageIndex = 1;
                    break;
                case "Image":
                    node.ImageIndex = 2;
                    node.SelectedImageIndex = 2;
                    break;
                case "File":
                    node.ImageIndex = 4;
                    node.SelectedImageIndex = 4;
                    break;
                default:
                    break;
            }
        }

        private void TsbDeleteMediaClick(object sender, EventArgs e)
        {
            if (tvMedias.SelectedNode == null)
	        {
		        MessageBox.Show("No node selected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
	        }
            string msg;
            switch (((Node)tvMedias.SelectedNode.Tag).NodeTypeAlias)
	        {
                case "Folder":
                    msg = "Are you sure that you want to delete the folder '" + tvMedias.SelectedNode.Text + "' with all his childs?";
                    break;
                case "Image":
                    msg = "Are you sure that you want to delete the image '" + tvMedias.SelectedNode.Text + "'?";
                    break;
                case "File":
                    msg = "Are you sure that you want to delete the file '" + tvMedias.SelectedNode.Text + "'?";
                    break;
		        default:
                    msg = "Are you sure that you want to delete the media '" + tvMedias.SelectedNode.Text + "'?";
                    break;
	        }
            if (MessageBox.Show(msg, "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Cursor = Cursors.WaitCursor;
                DeleteMediaNode(tvMedias.SelectedNode);
                tvMedias.SelectedNode.Parent.Nodes.Remove(tvMedias.SelectedNode);
                Cursor = Cursors.Default;
            }
        }

        private void DeleteMediaNode(TreeNode treeNode)
        {
            foreach (TreeNode childNode in treeNode.Nodes)
                DeleteMediaNode(childNode);
            actMedia.DeleteMedia(((Node)treeNode.Tag).Id);
        }

        private void TsbAddFolderClick(object sender, EventArgs e)
        {
            if (tvMedias.SelectedNode == null)
            {
                MessageBox.Show("There is no node selected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var folder = (Node)tvMedias.SelectedNode.Tag;

            using (var dlg = new Dialogs.AddFolderDialog())
            {
                if (dlg.ShowDialog(this) != DialogResult.OK) 
                    return;

                Cursor = Cursors.WaitCursor;
                var s = dlg.txtFoldername.Text;
                var treeNode = new TreeNode(s) {Tag = actMedia.CreateFolder(folder.Id, s)};
                SetImageIndex(treeNode, "Folder");
                tvMedias.SelectedNode.Nodes.Add(treeNode);
                Cursor = Cursors.Default;
            }
        }

        private void TsbAddImageClick(object sender, EventArgs e)
        {
            if (tvMedias.SelectedNode == null)
            {
                MessageBox.Show("There is no node selected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            var folderMedia = (Node)tvMedias.SelectedNode.Tag;

            using (var dlg = new Dialogs.AddImageDialog())
            {
                if (dlg.ShowDialog(this) != DialogResult.OK) 
                    return;

                Cursor = Cursors.WaitCursor;
                foreach (string s in dlg.lbxImages.Items)
                {
                    var treeNode = new TreeNode(System.IO.Path.GetFileName(s))
                                       {
                                           Tag =
                                               actMedia.CreateImage(folderMedia.Id,
                                                                    System.IO.Path.GetFileName(s),
                                                                    GetImage(s, dlg.MaxImageSize))
                                       };
                    SetImageIndex(treeNode, "Image");
                    tvMedias.SelectedNode.Nodes.Add(treeNode);
                }
                Cursor = Cursors.Default;
            }
        }

        private void TsbAddFileClick(object sender, EventArgs e)
        {
            if (tvMedias.SelectedNode == null)
            {
                MessageBox.Show("There is no node selected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var folder = (Node)tvMedias.SelectedNode.Tag;

            using (var dlg = new Dialogs.AddFileDialog())
            {
                if (dlg.ShowDialog(this) != DialogResult.OK) 
                    return;

                Cursor = Cursors.WaitCursor;
                foreach (string s in dlg.lbxImages.Items)
                {
                    var treeNode = new TreeNode(System.IO.Path.GetFileName(s))
                                       {
                                           Tag =
                                               actMedia.CreateFile(folder.Id, System.IO.Path.GetFileName(s),
                                                                   GetFile(s))
                                       };
                    SetImageIndex(treeNode, "File");
                    tvMedias.SelectedNode.Nodes.Add(treeNode);
                }
                Cursor = Cursors.Default;
            }
        }

        private void TsbAddStructureClick(object sender, EventArgs e)
        {
            if (tvMedias.SelectedNode == null)
            {
                MessageBox.Show("There is no node selected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var folder = (Node)tvMedias.SelectedNode.Tag;

            tvMedias.SuspendLayout();
            if (FolderBrowserDialog1.ShowDialog(this) == DialogResult.OK)
            {
                var selFolder = FolderBrowserDialog1.SelectedPath;
                
                foreach (var folderToAdd in System.IO.Directory.GetDirectories(selFolder))
                    AddFolder(folderToAdd, tvMedias.SelectedNode);
                
                foreach (var file in System.IO.Directory.GetFiles(selFolder))
                    if (System.IO.Path.GetExtension(file).ToLower().EndsWith("jpg"))
                    {
                        var newImageMedia = actMedia.CreateImage(folder.Id, System.IO.Path.GetFileName(file), GetImage(file, 1600));
                        var tnI = new TreeNode(newImageMedia.Name) {Tag = newImageMedia};
                        SetImageIndex(tnI, "Image");
                        tvMedias.SelectedNode.Nodes.Add(tnI);
                    }
                    else
                    {
                        var newFileMedia = actMedia.CreateFile(folder.Id, System.IO.Path.GetFileName(file), GetFile(file));
                        var tnF = new TreeNode(newFileMedia.Name) {Tag = newFileMedia};
                        SetImageIndex(tnF, "File");
                        tvMedias.SelectedNode.Nodes.Add(tnF);
                    }
            }
            tvMedias.PerformLayout();

            Cursor = Cursors.Default;
        }

        private void AddFolder(string folder, TreeNode parentNode)
        {
            var parentMediaFolder = (Node)parentNode.Tag;
            var newMediaFolder = actMedia.CreateFolder(parentMediaFolder.Id, new System.IO.DirectoryInfo(folder).Name);
            var tn = new TreeNode(newMediaFolder.Name) {Tag = newMediaFolder};
            SetImageIndex(tn, "Folder");
            parentNode.Nodes.Add(tn);

            foreach (var folderToAdd in System.IO.Directory.GetDirectories(folder))
                AddFolder(folderToAdd, tn);
            foreach (var file in System.IO.Directory.GetFiles(folder))
            {
                if (System.IO.Path.GetExtension(file).ToLower().EndsWith("jpg")) 
                {
                    var newImageMedia = actMedia.CreateImage(newMediaFolder.Id, System.IO.Path.GetFileName(file), GetImage(file, 1600));
                    var tnI = new TreeNode(newImageMedia.Name) {Tag = newImageMedia};
                    SetImageIndex(tnI, "Image");
                    tn.Nodes.Add(tnI);
                }
                else
                {
                    var newFileMedia = actMedia.CreateFile(newMediaFolder.Id, System.IO.Path.GetFileName(file), GetFile(file));
                    var tnF = new TreeNode(newFileMedia.Name) {Tag = newFileMedia};
                    SetImageIndex(tnF, "File");
                    tn.Nodes.Add(tnF);
                }
            }
        }

        private static byte[] GetImage(string fileName, int maxImageSize) 
        {
            ImageConverter ic;

            using (var image = Image.FromFile(fileName))
            {
                if (image.Height > maxImageSize || image.Width > maxImageSize)
                {
                    var bmp = GetScaledImage(image, maxImageSize);
                    var tempFileName = System.IO.Path.GetTempFileName();
                    bmp.Save(tempFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                    var buffer = GetFile(tempFileName);
                    System.IO.File.Delete(tempFileName);
                    return buffer;
                    //'bmp = New System.Drawing.Bitmap(image, image.Width, image.Height)
                }
                
                ic = new ImageConverter();
                return (byte[])(ic.ConvertTo(image, typeof(byte[])));
            }
        }

        private static byte[] GetFile(string s)
        {
            using (var fs = new System.IO.FileStream(s, System.IO.FileMode.Open))
            {
                var arr = new byte[Convert.ToInt32(fs.Length - 1)];
                fs.Position = 0;
                fs.Read(arr, 0, arr.Length);
                fs.Close();
                return arr;
            }
        }

        private static Bitmap GetScaledImage(Image img, int maxImageSize)
        {
            int w;
            int h;
            double fx;

            if (img.Width > img.Height)
            {
// ReSharper disable PossibleLossOfFraction
                fx = img.Width / maxImageSize;
// ReSharper restore PossibleLossOfFraction
                w = maxImageSize;
                h = Convert.ToInt32(img.Height / fx);
            }
            else
            {
                if (img.Height > img.Width)
                {
// ReSharper disable PossibleLossOfFraction
                    fx = img.Height / maxImageSize;
// ReSharper restore PossibleLossOfFraction
                    h = maxImageSize;
                    w = Convert.ToInt32(img.Width / fx);
                }
                else
                {
                    h = maxImageSize;
                    w = maxImageSize;
                }
            }
            return new Bitmap(img, w, h);
        }

    }
}
